<?php

namespace App\Service;

use App\Constants\QmGame;
use GuzzleHttp\Exception\GuzzleException;
use Hyperf\Guzzle\ClientFactory;
use Hyperf\Di\Annotation\Inject;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class MiMasterService {

    /**
     * @Inject
     * @var ClientFactory
     */
    protected ClientFactory $clientFactory;

    private array $config = [
        'offerId' => '1450036659'
    ];

    public function getOfferId() {
        return $this->config['offerId'];
    }

    /**
     * 请求米大师支付接口
     * @param $orderInfo
     * @return mixed
     * @throws ContainerExceptionInterface
     * @throws GuzzleException
     * @throws NotFoundExceptionInterface
     */
    public function doPay($orderInfo): mixed {
        $client = $this->clientFactory->create(['verify' => false]);
        $gameInfo = QmGameService::getGameInfo($orderInfo['game_hash']);
        $accessToken = $this->getAccessToken($gameInfo);

        $uri = '/cgi-bin/midas/pay';
        $url = "https://api.weixin.qq.com{$uri}?access_token={$accessToken}";
        $postData = [
            'openid'   => $orderInfo['openid'],
            'appid'    => $gameInfo['app_id'],
            'offer_id' => $this->config['offerId'],
            'ts'       => time(),
            'zone_id'  => '1',
            'pf'       => 'android',
            'amt'      => $orderInfo['money'] * 10,
            'bill_no'  => $orderInfo['order_num']
        ];
        $signStr = $this->getSignStr($postData, $uri);

        $response = $client->post($url, [
            'json' => [
                ...$postData,
                'sig' => $signStr
            ]
        ]);
        return json_decode($response->getBody()->getContents(), true);
    }

    /**
     * 查询米大师余额
     * @param $orderInfo
     * @return mixed
     * @throws GuzzleException
     */
    public function getBalance($orderInfo): mixed {
        $client = $this->clientFactory->create(['verify' => false]);
        $gameInfo = QmGameService::getGameInfo($orderInfo['game_hash']);
        $accessToken = $this->getAccessToken($gameInfo);

        $uri = '/cgi-bin/midas/getbalance';
        $url = "https://api.weixin.qq.com{$uri}?access_token={$accessToken}";
        $postData = [
            'openid'   => $orderInfo['openid'],
            'appid'    => $gameInfo['app_id'],
            'offer_id' => $this->config['offerId'],
            'ts'       => time(),
            'zone_id'  => '1',
            'pf'       => 'android'
        ];
        $signStr = $this->getSignStr($postData, $uri);

        $response = $client->post($url, [
            'json' => [
                ...$postData,
                'sig' => $signStr
            ]
        ]);

        return json_decode($response->getBody()->getContents(), true);
    }

    /**
     * 获取小程序AccessToken
     * @param $gameInfo
     * @return mixed
     * @throws GuzzleException
     */
    public function getAccessToken($gameInfo): mixed {
        $client = $this->clientFactory->create(['verify' => false]);
        $atPath = QmGame::MINI_APP_ACCESS_TOKEN . $gameInfo['app_id'];
        if (file_exists($atPath)) {
            $accessTokenConf = file_get_contents($atPath);
            $accessTokenArr = json_decode($accessTokenConf, true);
            if ($accessTokenArr['end'] >= time()) {
                return $accessTokenArr['value'];
            }
        }

        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$gameInfo['app_id']}&secret={$gameInfo['app_secret']}";
        $response = $client->get($url);
        $content = json_decode($response->getBody()->getContents(), true);
        if (isset($content['access_token'])) {
            $accessTokenArr = [
                'end'   => time() + 6000,
                'value' => $content['access_token']
            ];
            file_put_contents($atPath, json_encode($accessTokenArr));

            return $content['access_token'];
        } else {
            return '';
        }
    }

    /**
     * 文本合规检测
     * @param $gameInfo
     * @param $userInfo
     * @param $msg
     * @return bool
     * @throws GuzzleException
     */
    public function checkMsg($gameInfo, $userInfo, $msg): bool {
        $client = $this->clientFactory->create(['verify' => false]);
        $accessToken = $this->getAccessToken($gameInfo);

        $url = "https://api.weixin.qq.com/wxa/msg_sec_check?access_token={$accessToken}";
        $postData = [
            'openid'  => $userInfo['openid'],
            'scene'   => 2,
            'version' => 2,
            'content' => $msg
        ];
        $response = $client->post($url, [
            'body' => json_encode($postData, JSON_UNESCAPED_UNICODE)
        ]);
        $content = json_decode($response->getBody()->getContents(), true);
        if (isset($content['errcode']) && $content['errcode'] == 0) {
            return $content['result']['suggest'] === 'pass';
        } else {
            return true;
        }
    }

    /**
     * 图片合规检测
     * @param $gameInfo
     * @param $userInfo
     * @param $media_url
     * @return array
     * @throws GuzzleException
     */
    public function checkAvatar($gameInfo, $userInfo, $media_url): array {
        $client = $this->clientFactory->create(['verify' => false]);
        $accessToken = $this->getAccessToken($gameInfo);

        $url = "https://api.weixin.qq.com/wxa/media_check_async?access_token={$accessToken}";
        $postData = [
            'openid'     => $userInfo['openid'],
            'scene'      => 1,
            'version'    => 2,
            'media_type' => 2,
            'media_url'  => $media_url
        ];
        $response = $client->post($url, [
            'body' => json_encode($postData, JSON_UNESCAPED_UNICODE)
        ]);
        return json_decode($response->getBody()->getContents(), true);
    }

    /**
     * 计算支付秘钥
     * @param $data
     * @param $uri
     * @return false|string
     */
    private function getSignStr($data, $uri): bool|string {
        $key = 'xI0mnTeE8uBvZHNUhuz8eEvPUos3jYlA';
        ksort($data);

        $str = http_build_query($data) . "&org_loc={$uri}&method=POST&secret={$key}";

        return hash_hmac('sha256', $str, $key);
    }
}